// 设置标题
export const setDocumentTitle = function(title: string) {
  document.title = title
  const ua = navigator.userAgent
  // eslint-disable-next-line
  const regex = /\bMicroMessenger\/([\d\.]+)/
  if (regex.test(ua) && /ip(hone|od|ad)/i.test(ua)) {
    const i = document.createElement('iframe')
    i.src = '/favicon.ico'
    i.style.display = 'none'
    i.onload = function() {
      setTimeout(function() {
        i.remove()
      }, 9)
    }
    document.body.appendChild(i)
  }
}

// 判断是否有类名
export const hasClass = function(el: HTMLElement, cls: string): boolean {
  if (!el || !cls) return false
  if (cls.indexOf(' ') !== -1) throw new Error('className should not contain space.')
  if (el.classList) {
    return el.classList.contains(cls)
  } else {
    return (' ' + el.className + ' ').indexOf(' ' + cls + ' ') > -1
  }
}

// 添加类名
export const addClass = function(el: HTMLElement, cls: string) {
  if (!el) return
  let curClass = el.className
  const classes = (cls || '').split(' ')

  for (let i = 0, j = classes.length; i < j; i++) {
    const clsName = classes[i]
    if (!clsName) continue

    if (el.classList) {
      el.classList.add(clsName)
    } else if (!hasClass(el, clsName)) {
      curClass += ' ' + clsName
    }
  }
  if (!el.classList) {
    el.className = curClass
  }
}

// 删除类名
export const removeClass = function(el: HTMLElement, cls: string) {
  if (!el || !cls) return
  const classes = cls.split(' ')
  let curClass = ' ' + el.className + ' '

  for (let i = 0, j = classes.length; i < j; i++) {
    const clsName = classes[i]
    if (!clsName) continue

    if (el.classList) {
      el.classList.remove(clsName)
    } else if (hasClass(el, clsName)) {
      curClass = curClass.replace(' ' + clsName + ' ', ' ')
    }
  }
  if (!el.classList) {
    el.className = curClass.trim()
  }
}

// - 转驼峰
export const camelize = function(attr: string): string {
  // /\-(\w)/g 正则内的 (\w) 是一个捕获，捕获的内容对应后面 function 的 letter
  // 意思是将 匹配到的 -x 结构的 x 转换为大写的 X (x 这里代表任意字母)
  /* eslint-disable no-useless-escape */
  return attr.replace(/\-(\w)/g, function(all: string, letter: string) {
    return letter.toUpperCase()
  })
}

// 获取节点样式
export const getStyle = function(el: any, attr: string) { // 获得样式
  const style = window.getComputedStyle(el, null)
  if (style) {
    return style.getPropertyValue(attr)
  } else {
    return el.currentStyle.getAttribute(camelize(attr))
  }
}

// 判断节点是否可以滚动
export const judgeElAbleScroll = function(el: HTMLElement): boolean {
  if (el.scrollTop > 0) {
    return true
  } else {
    // 把节点滚动距离设为 1，如果可以滚动再获取就为 1，不能则为 0
    el.scrollTop = 1
    const scrollTop = el.scrollTop
    if (scrollTop > 0) {
      el.scrollTop = 0
      return true
    }
  }
  return false
}

// 获取滚动的父节点
export const getElAbleScrollParent = function(el: HTMLElement): HTMLElement | HTMLDocument {
  if (el.parentElement && el.parentElement.nodeName !== 'HTML') {
    if (judgeElAbleScroll(el.parentElement)) {
      return el.parentElement
    } else {
      return getElAbleScrollParent(el.parentElement)
    }
  } else {
    return document
  }
}

// 获取节点的 scrollTop
export const getElScrollTop = function(e: Event) {
  const target = e.target
  if (target instanceof HTMLDocument) {
    return document.documentElement.scrollTop
  } else if (target instanceof HTMLElement) {
    const elementTarget = target as HTMLElement
    return elementTarget.scrollTop
  }
  return 0
}

// 防抖(ts)
export class Debounced {
  /**
   * @param func 需要包装的函数
   * @param delay 延迟时间，单位ms
   * @param immediate 是否默认执行一次(第一次不延迟)
   */
  public use = (func: Function, delay: number, immediate = false): Function => {
    let timer: number | undefined
    return (...args: any) => {
      if (immediate) {
        func.apply(this, args) // 确保引用函数的指向正确，并且函数的参数也不变
        immediate = false
        return
      }
      clearTimeout(timer)
      timer = setTimeout(() => {
        func.apply(this, args)
      }, delay)
    }
  }
}

// 节流(ts)
export class Throttle {
  private timer: number | undefined
  private stop = false
  private death = false
  /**
   * @param func 需要包装的函数
   * @param delay 延迟时间，单位ms
   * @param immediate 是否默认执行一次(第一次不延迟)
   */
  public use(func: Function, delay: number, immediate = false): Function {
    let flag = true
    // eslint-disable-next-line @typescript-eslint/no-this-alias
    const self = this
    return (...args: any) => {
      if (this.death) {
        func.apply(this, args)
        return
      }
      if (this.stop) {
        func.apply(this, args)
        return
      }
      if (immediate) {
        func.apply(this, args)
        immediate = false
        return
      }
      if (!flag) {
        return
      }
      flag = false
      self.timer = setTimeout(() => {
        func.apply(this, args)
        flag = true
      }, delay)
    }
  }

  // 销毁
  public destroy() {
    this.death = true
    this.stop = true
    if (this.timer) {
      clearTimeout(this.timer)
      this.timer = undefined
    }
  }
  // 开启
  public open() {
    if (!this.death) {
      this.stop = false
    }
  }
  // 关闭
  public close() {
    this.stop = true
  }
}

export interface Rect {
  width: number,
  height: number,
}

// 获取节点大小
export const getSize = function(el: HTMLElement): Rect {
  const oladDisplay: string = getStyle(el, 'display')
  const oladPosition: string = getStyle(el, 'position')
  const oladVisibility: string = getStyle(el, 'visibility')

  let callback

  if (oladDisplay === 'none') {
    el.style.display = ''
    el.style.position = 'absolute'
    el.style.visibility = 'hidden'
    callback = function() {
      el.style.display = oladDisplay
      el.style.position = oladPosition
      el.style.visibility = oladVisibility
    }
  }

  const rect: Rect = {
    width: el.clientWidth,
    height: el.clientHeight,
  }

  typeof callback === 'function' && callback()

  return rect
}

// 乱序数组
export const shuffle = function(arr: any[]) {
  for (let i = arr.length - 1; i >= 0; i--) {
    const rIndex = Math.floor(Math.random() * (i + 1))
    const temp = arr[rIndex]
    arr[rIndex] = arr[i]
    arr[i] = temp
  }
  return [...arr]
}

